#include <cpp_redis/cpp_redis>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <signal.h>
#include <winsock_initializer.h>
#include "BaseCmdParam.h"
// 命令行参数解析器
class ClientConfig : public gdface::BaseClientConfig {
public:
	const std::string PARAM_CHANNEL_NAME = "channel";
	const std::string PARAM_AUTH = "auth";

	std::string channel;
	std::string password;
	ClientConfig():gdface::BaseClientConfig(),channel(),password() {
		cmdparam.add<std::string>(PARAM_CHANNEL_NAME, 'c', "channel name for subscribing", false, "c1");
		cmdparam.add<std::string>(PARAM_AUTH, 'a', "password for authorization", false, "");
	}
	~ClientConfig() = default;
	void afterParse() {
		gdface::BaseClientConfig::afterParse();
		channel = cmdparam.get<std::string>(PARAM_CHANNEL_NAME);
		password = cmdparam.get<std::string>(PARAM_AUTH);
	}
};

std::condition_variable should_exit;

void
sigint_handler(int) {
	should_exit.notify_all();
}

int
main(int argc, char *argv[]) {
	ClientConfig param;
	param.parse(argc, argv);

	winsock_initializer winsock_init;
	//! Enable logging
	cpp_redis::active_logger = std::unique_ptr<cpp_redis::logger>(new cpp_redis::logger);

	cpp_redis::subscriber sub;

	sub.connect(param.host, param.port, [](const std::string& host, std::size_t port, cpp_redis::connect_state status) {
		if (status == cpp_redis::connect_state::dropped) {
			std::cout << "client disconnected from " << host << ":" << port << std::endl;
			should_exit.notify_all();
		}
		switch(status){
		case  cpp_redis::connect_state::dropped:
			std::cout << "client disconnected from " << host << ":" << port << std::endl;
			should_exit.notify_all();
			break;
		case cpp_redis::connect_state::start:
			std::cout << "client connect to " << host << ":" << port << ",press CTRL-C for exit" << std::endl;
			break;
		default:
			break;
		}
	});

	if(!param.password.empty()){
		//! authentication if server-server requires it
		sub.auth(param.password, [](const cpp_redis::reply& reply) {
			if (reply.is_error()) {
				std::cerr << "Authentication failed: " << reply.as_string() << std::endl;
				should_exit.notify_all();
			} else {
				std::cout << "successful authentication" << std::endl;
			}
		});
	}
	sub.subscribe(param.channel, [](const std::string& chan, const std::string& msg) {
		std::cout << "MESSAGE " << chan << ": " << msg << std::endl;
	});
	sub.psubscribe("*", [](const std::string& chan, const std::string& msg) {
		std::cout << "PMESSAGE " << chan << ": " << msg << std::endl;
	});
	sub.commit();

	signal(SIGINT, &sigint_handler);
	std::mutex mtx;
	std::unique_lock<std::mutex> lock(mtx);
	should_exit.wait(lock);

	return 0;
}
